
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <uapi/linux/input.h>
#include <linux/input.h>
#include <linux/input/mt.h>

#include "ramdisk.h"

#if NON_REQUEST_QUEUE
static void ramdisk_make_request(struct request_queue *queue, struct bio *bio)
{
    int offset;
    struct bio_vec bvec;
    struct bvec_iter iter;
    unsigned long len = 0;

    offset = bio->bi_iter.bi_sector << 9;    /* 要操作的磁盘起始扇区偏移, 改为字节地址 */

    /* 循环处理每个段 */
    bio_for_each_segment(bvec, bio, iter)
    {
        /* 获取bio里面的缓冲区
         * 如果是读：从磁盘里面读取到的数据保存在此缓冲区里面
         * 如果是写：此缓冲区保存着要写入到磁盘的数据*/
        char *ptr = page_address(bvec.bv_page) + bvec.bv_offset; 
        len = bvec.bv_len;

        if (bio_data_dir(bio) == READ)
        {
            memcpy(ptr, ramdisk.ramdiskbuf + offset, len);     // 读操作
        }
        else
        {
            memcpy(ramdisk.ramdiskbuf + offset, ptr, len);     // 写操作
        }
        offset += len;
    }

    set_bit(BIO_UPTODATE, &bio->bi_flags);
    bio_endio(bio, 0);
}
#else
static void ramdisk_request_fn(struct request_queue *q)
{
    int err = 0;
    struct request *req;

    req = blk_fetch_request(q);
    while (req)
    {
        /* 处理request，数据读写操作 */
        if (!__blk_end_request_cur(req, err))
        {
            req = blk_fetch_request(q);
        }
    }
    return;
}
#endif

static void ramdisk_transfer(struct request *req)
{
    /* 数据传输的三要素：源，目的，长度(内存地址，块设备地址，长度) */

    /* 获取到要操作的块设备扇区地址, 左移9位 */
    unsigned long start = blk_rq_pos(req) << 9;
    unsigned long len = blk_rq_cur_bytes(req);

    /* 获取bio里面的缓冲区：
     * 如果是读：从磁盘里面读取到的数据保存在此缓冲区里面
     * 如果是写：此缓冲区保存着要写入到磁盘的数据*/
    void *buffer = bio_data(req->bio);

    if (rq_data_dir(req) == READ)
    {
        memcpy(buffer, ramdisk.ramdiskbuf + start, len);     // 读操作
    }
    else
    {
        memcpy(ramdisk.ramdiskbuf + start, buffer, len);     // 写操作
    }
}

static int ramdisk_open(struct block_device *bdev, fmode_t mode)
{

    printk("ramdisk open function\r\n");
    return 0;
}
static void ramdisk_release(struct gendisk *bdev, fmode_t mode)
{

    printk("ramdisk release function\r\n");
}
static int ramdisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{

    printk("ramdisk getgeo function\r\n");
    return 0;
}

static const struct block_device_operations ramdisk_fops = {
    .owner      = THIS_MODULE,
    .open       = ramdisk_open,
    .release    = ramdisk_release,
    .getgeo     = ramdisk_getgeo,
};

static int __init ramdisk_init(void)
{
    int ret;
    printk("ramdisk drivers init\r\n");

    /* 1. 申请内存 */
    ramdisk.ramdiskbuf = kzalloc(RAMDISK_SIZE, GFP_KERNEL);
    if (ramdisk.ramdiskbuf == NULL)
    {
        ret = -EINVAL;
        goto ramalloc_fail;
    }

    /* 2. 注册块设备 */
    ramdisk.major = register_blkdev(0, RAMDISK_NAME);
    if(ramdisk.major < 0)
    {
        ret = -EINVAL;
        goto ramdisk_register_blkdev_fail;
    }
    printk("ramdisk major = %d\r\n", ramdisk.major);

    /*3. 申请gendisk */
    ramdisk.gendisk = alloc_disk(RAMDISK_MINOR);
    if (ramdisk.gendisk == NULL)
    {
        ret = -EINVAL;
        goto gendisk_alloc_fail;
    }

    /* 4 初始化自旋锁 */
    spin_lock_init(&ramdisk.lock);


    /* 5 申请并初始化请求队列 */
#if NON_REQUEST_QUEUE
    ramdisk.queue = blk_alloc_queue(GFP_KERNEL);
#else
    ramdisk.queue = blk_init_queue(ramdisk_request_fn, &ramdisk.lock);
#endif
    if (!ramdisk.queue)
    {
        ret = -EINVAL;
        goto blk_queue_fail;
    }

#if NON_REQUEST_QUEUE
    /* 绑定制造请求函数 */
    blk_queue_make_request(ramdisk.queue, ramdisk_make_request);
#endif
    /* 6. 初始化gendisk */
    ramdisk.gendisk->major = ramdisk.major;
    ramdisk.gendisk->first_minor = 0;
    ramdisk.gendisk->fops = &ramdisk_fops;
    ramdisk.gendisk->private_data = &ramdisk;
    ramdisk.gendisk->queue = ramdisk.queue;
    sprintf(ramdisk.gendisk->disk_name, RAMDISK_NAME);
    set_capacity(ramdisk.gendisk, RAMDISK_SIZE / 512);  /* 设置容量, 单位：扇区 */
    add_disk(ramdisk.gendisk);

    return 0;


blk_queue_fail:
    put_disk(ramdisk.gendisk);
gendisk_alloc_fail:
    unregister_blkdev(ramdisk.major, RAMDISK_NAME);
ramdisk_register_blkdev_fail:
    kfree(ramdisk.ramdiskbuf);
ramalloc_fail:
    return ret;
}

static void __exit ramdisk_exit(void)
{
    printk("ramdisk drivers exit\r\n");

    del_gendisk(ramdisk.gendisk);
    put_disk(ramdisk.gendisk);

    blk_cleanup_queue(ramdisk.queue);
    unregister_blkdev(ramdisk.major, RAMDISK_NAME);
    kfree(ramdisk.ramdiskbuf);
}

module_init(ramdisk_init);
module_exit(ramdisk_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xue");


